home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr10 / v12n12.zip / PCMCVT.ZIP / PCMASM.ZIP / PCMCVT.ASM < prev    next >
Assembly Source File  |  1993-05-29  |  27KB  |  875 lines

  1. ;--------------------------------------------------------------------------
  2. ;PCMCVT.ASM
  3. ;Version 1.0
  4. ;Copyright (c) 1993 Jay Munro
  5. ;First published in PC Magazine June 29,1993
  6. ;--------------------------------------------------------------------------
  7. ;
  8. ;Compile and link with Masm 6.x:
  9. ;  ML /Gc /Zm /W3 PCMCVT.ASM
  10. ;
  11. ;--------------------------------------------------------------------------
  12. .Model Tiny                     ;Tiny model with Masm 6.x
  13. .Code                           ;code segment (et all)
  14. Org 100h                        ;origin for executable code, 100h
  15.  
  16. MakeText Proc Near
  17.  
  18. Begin:                          ;start here 
  19.     Jmp SetErrorTrap
  20.  
  21. Include   PCMDATA.INC           ;data file for PCMCVT
  22.  
  23. SetErrorTrap:
  24.     Invoke PrintLine, Addr Copyright  ;first print our copyright
  25.     Call   HookInt24            ;set int 24h handler right off the bat!
  26.     Mov    CS:CritErrFlag,0     ;clear CritErrFlag
  27.     Mov    AX,CS
  28.     Mov    ES,AX                ;get our segments in line
  29.     Mov    DS,AX
  30.     Mov    Byte Ptr TabFlag,0   ;clear some of our variables
  31.     Mov    Byte Ptr OverWriteFile,0
  32.     Cld                         ;forward moves
  33.     Mov     SI,80H              ;Point to parameter
  34.     LodSb
  35.     Cmp     AL,1                ;any parm length?
  36.     Jg      GetParms
  37.     Call    HelpPrint           ;give the user a little prod
  38.     Jmp     Exit                ;no parms
  39.  
  40. GetParms:
  41.     Call   GetCommandString             ;parse out our options
  42.     Jc     ExitLeap
  43.     Cmp    SourceFileThere,-1           ;if the file is there...ok
  44.     Jz     OpenFiles
  45.  
  46. NoSourceFile:
  47.     Invoke PrintLine, Addr SourceRequired  ;print message
  48.     Jmp     Exit                        ;no parms
  49.  
  50. OpenFiles:
  51.     Invoke OpenFile, Addr SourceFile, 0    ;open source
  52.     Mov    SHandle,AX                      ;save handle
  53.     Jc     ErrorLeap                       ;quit if error
  54.     Invoke Read, SHandle, Addr HeaderBuffer, 256  ;read header
  55.     Jc     ErrorLeap                       ;again exit if error
  56.     Invoke Seek, SHandle, 0                ;reset to zero on seek
  57.     Jc     ErrorLeap                       ;good ol' error trapping
  58.     Call   HeadCheck                       ;check header for file type
  59.     Jmp    Stripper
  60.     
  61. ;---------------------------------------------------------------------------
  62. ErrorLeap:
  63.     Call   PrintError
  64.     
  65. ExitLeap:                               ;mid-way lily pad for short jumps
  66.     Jmp    Exit
  67.  
  68. Stripper:
  69.     Cmp    Word Ptr FileType,-1         ;ok, did we find a file?
  70.     Jz     ExitLeap                     ;nope...exit stage left
  71.     
  72.     Cld                                 ;forward direction on our moves
  73.     Cmp    OverWriteFile,-1
  74.     Jz     @F                           ;overwrite all the time
  75.     Invoke Exist, Addr DestFile
  76.     Jc     @F                           ;not there, create it
  77.     Call   ExistYes
  78.     Jnc    @F
  79.     Mov    AL,2                         ;exit code
  80.     Jmp    Exit                         ;if carry set, then exit now
  81.      
  82. @@:
  83.     Invoke OpenFile, Addr DestFile, 3C00h  ;write - open or create
  84.     Jc     ErrorLeap
  85.     Mov    DHandle,AX
  86.  
  87. ;WordPerfect
  88.     Lea    DI,WriteBuffer               ;point DI at Write buffer
  89.     Xor    BX,BX                        ;initialize counter for write buffer
  90.     Mov    AX,FileType
  91.     Cmp    AX,1                         ;1 = WordPerfect
  92.     Jnz    W4D                          ;no this ain't it
  93.     Call   WordPerfectCVT
  94.     Jmp    ExitLeap
  95.  
  96. ;Word For DOS
  97. W4D:
  98.     Cmp    AX,2                         ;2 = word for dos
  99.     Jnz    W4W                          ;no this
  100.     Call   Word4DosCVT
  101.     Jmp    ExitLeap
  102.  
  103. ;Word For Windows
  104. W4W:
  105.     Cmp    AX,3                         ;3 = word for dos
  106.     Jnz    AMI2                         ;no this
  107.     Call   Word4WINCVT
  108.     Jmp    ExitLeap
  109.  
  110. ;AMIPro
  111. AMI2:
  112.     Cmp    AX,4                         ;4 = AMI Pro
  113.     Jnz    WinWri                       ;no this
  114.     Call   AMIProCVT
  115.     Jmp    ExitLeap
  116.  
  117. ;Windows Write
  118. WinWri:
  119.     Cmp    AX,5                         ;5 = Windows Write
  120.     Jnz    ExitLeap                     ;no this
  121.     Call   WRICVT
  122.  
  123. Exit:
  124.     Cmp    AL,-1
  125.     Jnz    @F
  126.     Xor    AX,AX
  127. @@:
  128.     Push   AX
  129.     Cmp    Word Ptr SHandle, 0
  130.     Jz     @F
  131.     Invoke Close, SHandle
  132. @@:
  133.     Cmp    Word Ptr DHandle, 0
  134.     Jz     @F
  135.     Invoke Close, DHandle
  136. @@:
  137.     Xor    DX,DX
  138.     Call   UnHookInt24                  ;put back int 24h
  139.     Pop    AX                           ;retrieve error code
  140.     Mov    AH,4Ch                       ;exit here
  141.     Int    21h
  142. MakeText   EndP
  143.  
  144. FlushIt Proc Near                       ;flushes write buffer
  145.     Mov   AL,-1
  146.     Call  WriteIt
  147.     Ret
  148. FlushIt EndP
  149.  
  150. ;----Write character    ES:DI points at buffer
  151. WriteIt Proc Near
  152.     Cmp   AL,-1                  ;are we flushing?
  153.     Jz    Flush
  154.     StoSb
  155.     Inc   BX                     ;register a character in buffer
  156.     Cmp   Word Ptr BufferSize,BX
  157.     Jae   WriteItExit
  158.  
  159. Flush:
  160.     Push  SI                     ;save counter and source addr
  161.     Push  CX
  162.     Push  BX
  163.  
  164. ;Word wrap routine here
  165.     Cmp   Byte Ptr WordWrapFlag,-1           ;are we doing word wrap?
  166.     Jnz   NoWrap
  167.     Invoke WordWrap, Addr WriteBuffer, BX    ;do our word wrap magic
  168.     Jmp   @F
  169.  
  170. NoWrap:
  171.     Invoke Write, DHandle, Addr WriteBuffer,BX          ; BufferSize   ;write it
  172.     Jc    WriteItExit
  173.  
  174. @@:
  175.     Pop   BX
  176.     Lea   DI,WriteBuffer
  177.     Xor   BX,BX
  178.     Pop   CX                    ;retrieve counter & source addr
  179.     Pop   SI
  180.     Mov   AL,-1                 ;signal a flush
  181. WriteItExit:
  182.     RetN
  183. WriteIt EndP
  184.  
  185. Exist Proc Near, FileName:Word
  186.    Mov  DX,Offset DTA           ;set DTA address
  187.    Mov  AH,1Ah
  188.    Int  21h                     ;service 1Ah, int 21h
  189.    Mov  AH,4Eh                  ;find first, service 4Eh
  190.    Xor  CX,CX                   ;normal file attribute
  191.    Mov  DX,FileName             ;file to check for
  192.    Int  21h
  193.    Ret
  194. Exist EndP
  195.  
  196. ReadIt Proc Near
  197.     Push   DX
  198.     Push   BX
  199.     Xor    AL,AL                        ;clear AL for attribute
  200.     Invoke Read,SHandle,Addr ReadBuffer, BufferSize     ;read beginning
  201.     Pop    BX
  202.     Pop    DX
  203.     Jnc    @F
  204.     Jmp    ExitReadit
  205.  
  206. @@:
  207.     Or     AX,AX                        ;if AX is 0 then bag out
  208.     Jnz    @F
  209.     Stc
  210.     Jmp    ExitReadIt
  211.  
  212. @@:
  213.     Mov    CX,AX                        ;CX = number of bytes
  214.     Cmp    CX,BufferSize                ;are we in the ballpark?
  215.     Jz     @F
  216.     Mov    BufferSize,CX                ;nope reset
  217.     Mov    EOFFlag,-1                   ;set EOF flag
  218. @@:
  219.     Clc
  220.     Lea    SI,ReadBuffer                ;point SI at buffer
  221.     Mov    TopEnd, SI
  222.     Add    TopEnd,CX
  223.     
  224. ExitReadit:
  225.     RetN
  226. ReadIt EndP
  227.  
  228. ;---Include files
  229. Include    SEARCH.INC           ;Search module used in AMI module
  230. Include    WP51CONV.INC         ;WordPerfect conversion module
  231. Include    W4DCONV.INC          ;Word For Dos conversion module
  232. Include    W4WCONV.INC          ;Word For Win conversion module
  233. Include    AMICONV.INC          ;AMI Pro conversion module
  234. Include    WriCONV.INC          ;Windows Write conversion module
  235.  
  236. GetCommandString Proc Near      ;parses out command string
  237.    Mov     BX,SI                ;save SI (reuse)
  238.  
  239. CapIt:                          ;capitalizes the command line
  240.                                 ;  bet you thought DOS did that?
  241.    LodSb                        ;grab a byte
  242.    Or      AL,AL                ;is it a zero?
  243.    Jz      CapDone              ;all done, retrieve old pointer
  244.    
  245.    Cmp     AL,'a'               ;is it within the range of a - z ?
  246.    Jl      CapIt
  247.    Cmp     AL,'z'
  248.    Jg      CapIt
  249.    Sub     AL,32                ;capitalize it
  250.    Mov     Byte Ptr [SI-1],AL   ;put cap'd letter back
  251.    Jmp     CapIt                ;loop back
  252.  
  253. CapDone:
  254.    Mov     SI,BX                ;put SI back
  255.  
  256. EatCmdSpace:
  257.    LodSb                        ;get a character
  258.    Cmp     AL,'/'               ;is it a delimiter?
  259.    Jz      ParseOMatic
  260.    Cmp     AL,0                 ;is it the end of the line?
  261.    Jz      CMDDoneLily
  262.    Cmp     AL,32                ;is it a space?
  263.    Jz      EatCmdSpace          ;yes, eatit
  264.    Cmp     AL,0Dh               ;carriage return
  265.    Jz      CmdDoneLily
  266.    Jmp     EatCmdSpace
  267.  
  268. ParseOMatic:                    ;parse commands
  269.    LodSb                        ;get command letter
  270.  
  271. ;check for dest file
  272.    Cmp     AL,'D'               ;Destfile?
  273.    Jnz     @F
  274.    Mov     Byte Ptr DestFileThere, -1  ;set file flag
  275.    Invoke  ParseFileName, ADDR DestFile
  276.    Jc      CMDDoneLily
  277.    Jmp     EatCmdSpace
  278.  
  279. CMDDoneLily:
  280.    Clc                          ;set carry, were still in
  281.    Jmp     CmdDone
  282.    
  283. @@:
  284.    Cmp     AL,'S'               ;source file
  285.    Jnz     @F
  286.    Mov     Byte Ptr SourceFileThere, -1  ;set file flag
  287.    Invoke  ParseFileName, ADDR SourceFile
  288.    Jc      CmdDoneLily
  289.    Jmp     EatCmdSpace
  290.  
  291. @@:
  292.    Cmp     AL,'W'               ;word wrap
  293.    Jnz     @F
  294.    Mov     WordWrapFlag,-1
  295.  
  296. WLoop:
  297.    Cmp     Byte Ptr [SI],'/'    ;if we hit a slash, then we're done
  298.    Jz      NoWNumber
  299.    Cmp     Byte Ptr [SI],0Dh    ;carriage return
  300.    Jz      NoWNumber            ;also done
  301.    Cmp     Byte Ptr [SI],32     ;check for a value.
  302.    Jnz     GetWWValue
  303.    Inc     SI                   ;point to next character
  304.    Jmp     WLoop                ;eat spaces
  305.    
  306. GetWWValue:
  307.    Invoke  ParseFileName, ADDR MaxWidthText     ;parse out the number
  308.    Invoke  Text2Num, Addr MaxWidthText, Addr MaxWidth ;convert the number
  309.  
  310. NoWNumber:
  311.    Jmp     EatCmdSpace
  312.  
  313. @@:
  314.    Cmp     AL,'T'                               ;Tab expansion
  315.    Jnz     @F
  316.    Invoke  ParseFileName, ADDR TabWidthText     ;parse out the number
  317.    Invoke  Text2Num, Addr TabWidthText, Addr TabWidth   ;convert the number
  318.    Mov     Byte Ptr TabFlag, -1                 ;signal we are doing tabs
  319.    Jmp     EatCmdSpace
  320.    
  321. @@:
  322.    Cmp     AL,'O'               ;overwrite file
  323.    Jnz     @F
  324.    Mov     OverWriteFile,-1
  325.    Jmp     EatCmdSpace
  326.  
  327. @@:
  328.    Cmp     AL,'?'               ;help
  329.    Jnz     @F
  330.    Call    HelpPrint
  331.    Stc                          ;Set carry to exit
  332.    Jmp     HelpDone
  333.    
  334. @@:
  335.    Jmp     EatCmdSpace          ;loop back til end
  336.  
  337. CmdDone:
  338.    Call    CheckDestFile
  339.    Clc
  340. HelpDone:
  341.    Ret
  342. GetCommandString EndP
  343.  
  344. ParseFileName Proc Near, FileBuffer:Ptr
  345.                                 ;entry DS:SI points toward string
  346.   Mov   DI,FileBuffer           ;point ES:DI at buffer
  347.   Xor   CX,CX                   ;clear CX for a counter
  348.   
  349. PSLoop:
  350.   LodSb                         ;grab a character
  351.   Cmp   AL,32                   ;is it a space?
  352.   Jnz   @F                      ;no
  353.   Jcxz  PSLoop                  ;nope, then eat leading spaces
  354.   Clc                           ;clear carry and go out
  355.   Jmp  PFNOut                   ;bye
  356.  
  357. @@:
  358.   Or    AL,AL                   ;is it a zero?
  359.   Jnz   @F
  360.   Stc
  361.   Jmp   PFNOut
  362.   
  363. @@:
  364.   Cmp     AL,0Dh                ;carriage return
  365.   Jnz   @F
  366.   Stc
  367.   Jmp   PFNOut
  368.  
  369. @@:
  370.   StoSb                         ;assume it's a character and store it
  371.   Inc   CX                      ;character counter
  372.   Cmp   CX, 66                  ;max out at 66
  373.   Jle   PSLoop
  374.   Clc                           ;bug out
  375.  
  376. PFNOut:
  377.   Mov   [DI],CH                 ;put a zero on the end of the file name
  378.   Ret
  379. ParseFileName EndP
  380.  
  381. ;--- Headcheck, identifies file by header.
  382.  
  383. HeadCheck Proc Near
  384. ;---------------------------------------------------------------------------
  385. ;-- WordPerfect
  386.   Invoke StrCmp, Addr HeaderBuffer, Addr WPerfID,4
  387.   Or   AX,AX
  388.   Jnz  @F
  389.   Mov  AX,1                     ;1 = Word Perf
  390.   Lea  DX,WPerfName             ;print name
  391.   Jmp  HeadOut
  392. @@:
  393.  
  394. ;---------------------------------------------------------------------------
  395. ;-- Word For DOS                ;
  396.   Invoke StrCmp, Addr HeaderBuffer, Addr MSWordDosID, 2
  397.   Or   AX,AX
  398.   Jnz  @F
  399.  
  400. ;Check for Write file
  401.   Mov  BX, Offset HeaderBuffer
  402.   Cmp  Word Ptr [BX].MSWdwReserve, 0
  403.   Jnz  WriFile
  404.   Mov  AX,2                     ;2 = Word4DOS
  405.   Lea  DX,MSW4DName             ;print name
  406.   Jmp  HeadOut
  407.  
  408. WriFile:                        ;Windows Write format
  409.   Mov  AX,5
  410.   Lea  DX,WRIName               ;print name
  411.   Jmp  HeadOut 
  412.   
  413. ;---------------------------------------------------------------------------
  414. ;-- Word For Windows            
  415. @@:
  416.   Invoke StrCmp, Addr HeaderBuffer, Addr MSWordWinID,2
  417.   Or   AX,AX
  418.   Jnz  @F
  419.   Mov  AX,3                     ;3 = Word for Windows
  420.   Lea  DX,MSW4WName             ;print name
  421.   Jmp  HeadOut
  422.  
  423. @@:
  424.   Invoke StrCmp, Addr HeaderBuffer, Addr MSWordWinID1,2
  425.   Or   AX,AX
  426.   Jnz  @F
  427.   Mov  AX,3                     ;3 = Word for Windows 1
  428.   Lea  DX,MSW4WName1            ;print name
  429.   Jmp  HeadOut
  430.  
  431. ;---------------------------------------------------------------------------
  432. ;-- Ami Pro
  433. @@:
  434.   Invoke StrCmp, Addr HeaderBuffer, Addr AMIProID,5
  435.   Or   AX,AX
  436.   Jnz  @F
  437.   Mov  AX,4                     ;4 = AMIPro 2.0
  438.   Lea  DX,AmiName               ;print name
  439.   Jmp  HeadOut
  440.  
  441. ;---------------------------------------------------------------------------
  442. @@:
  443.   Lea  DX,NotKnown              ;no idea!
  444.   Mov  AX,-1
  445.   
  446. HeadOut:                        ;print type of file
  447.   Mov  FileType, AX 
  448.   Mov  AH,09h
  449.   Int  21h
  450.   Ret
  451. HeadCheck EndP
  452.  
  453. PrintLine Proc Near, MessagePtr:Word
  454.   Mov  DX, MessagePtr
  455.   Mov  AH,09h
  456.   Int  21h
  457.   Ret
  458. PrintLine EndP
  459.  
  460. ShowBuffer Proc Near, AddrWriteBuffer:Word, BuffLen:Word   ;do it to the screen.
  461.   Cld                           ;forward direction flag
  462.   Push  CX                      ;preserve CX & SI for
  463.   Push  SI
  464.   Mov   SI,AddrWriteBuffer
  465.   Mov   CX,BuffLen
  466.  
  467. CharLoop:
  468.   LodSb
  469.   Mov   AH,0Eh
  470.   Xor   BX,BX
  471.   Int   10h
  472.   Loop  CharLoop
  473.   Pop   SI
  474.   Pop   CX   
  475.   Ret
  476. ShowBuffer EndP
  477.  
  478. Text2Num  Proc Near Uses DI SI, ValueStr:Word, ValueNum:Word
  479.    Cld
  480.    Mov   SI,ValueStr                    ;get address of value string
  481.    Mov   BX,10
  482.    Xor   DX,DX
  483.    Mov   AX,DX
  484.    
  485. FindZero:
  486.    LodSb
  487.    Or    AL,AL                          ;is it zero?
  488.    Jz    @F
  489.    Xchg  AX,DX                          ;Swap for multiply
  490.    Mul   BL                             ;multiply by 10
  491.    Xchg  DX,AX
  492.    Xor   AH,AH
  493.    Sub   AL,'0'                         ;make it a real number
  494.    Add   DX,AX                          ;add it in
  495.    Jmp   FindZero
  496. @@:
  497.    Mov   BX,ValueNum                    ;stick total into return value
  498.    Mov   [BX],DX
  499.    Ret
  500. Text2Num  EndP
  501.  
  502. DoTabs Proc Near Uses CX                ;expand tabs
  503.    Cmp   TabFlag,0                      ;check to see if we save a tab
  504.    Jnz   @F                             ;  or replace with spaces
  505.    Mov   AL,9h                          ;put a tab in AL
  506.    Call  WriteIt                        ;write just the tab
  507.    Jmp   TabExit
  508.    
  509. @@:
  510.    Mov   CX, TabWidth                   ;get tab size
  511.    Jcxz  TabExit
  512.    
  513. TabLoop:
  514.    Mov   AL,32                          ;put space in AL
  515.    Call  WriteIt
  516.    Loop  TabLoop
  517.  
  518. TabExit:
  519.    Ret
  520.  
  521. DoTabs EndP
  522.  
  523. Include WordWrap.Inc
  524. ;---------------------------------------------------------------------------
  525. ;File and error routines 
  526. ;----------------------------------------------------------------------------
  527. ;HookInt24 - redirects critical errors to a more friendly handler.
  528. ;            On a Critical error, the int 24h is captured and the error
  529. ;            is returned to the calling routine.
  530. ;redirects Int24 to our own error handler
  531.  
  532. HookInt24  Proc Near
  533.     Mov    AX,3524h                    ;get Int24 vector
  534.     Int    21h                         ;  into ES:BX
  535.     Mov    OldInt24IP,BX               ;  and save.
  536.     Mov    OldInt24CS,ES
  537.     Lea    DX,Int24ErrHandler          ;DS = CS of CEH
  538.     Mov    AX,2524h                    ;revector Int24h
  539.     Int    21h
  540.     Retn
  541. HookInt24  EndP
  542.  
  543. ;Restores the original Int24 vector that was saved by HookInt24
  544. UnHookInt24 Proc Far
  545.     Push   DS                          ;save registers
  546.     Push   DX
  547.     Push   AX
  548.     Push   SS                          ;set DS = DGROUP
  549.     Pop    DS
  550.     Mov    DX,OldInt24IP               ;get the original Int24 vector
  551.     Mov    DS,OldInt24CS
  552.     Mov    AX,2524h                    ;restore the vector
  553.     Int    21h
  554.     Pop    AX                          ;restore registers
  555.     Pop    DX
  556.     Pop    DS
  557.     Ret
  558. UnHookInt24 EndP
  559.  
  560. HelpPrint Proc Near                    ;shows help screen
  561.     Mov  AH,09h
  562.     Mov  DX,Offset HelpScreen
  563.     Int  21h
  564.     Ret
  565. HelpPrint EndP
  566.  
  567. ;Error handler - returns error to interrupt and continues.
  568. ; On entry: Error code in DI (provided by DOS)
  569. ; On exit:  DOSErrCode = Critical error
  570. ;           AL directs DOS to ignore the error
  571. Int24ErrHandler Proc Near               ;our new error handler
  572.     Sti                                 ;restore interrupts
  573.     Push   DI                           ;save DI
  574.     Push   DX                           ;save DX
  575.     Push   DS                           ;save DS
  576.     Push   AX                           ;save AX
  577. ;translate error
  578.     Mov    AX,99                        ;unknown error default
  579.     Cmp    DI,0h                        ;write protect
  580.     Jnz    @F
  581.     Mov    AX, 13h
  582. @@:
  583.     Cmp    DI, 02h                      ;disk not ready
  584.     Jnz    @F
  585.     Mov    AX, 15h
  586. @@:
  587. NotDiskIO:
  588.     Mov    CS:DOSErrCode,AX
  589.     
  590. CEH_Exit:
  591.     Mov    CS:CritErrFlag,1            ;verify that a critical error occurred
  592.     Pop    AX                          ;restore AX (really just AH)
  593.     Mov    AL,0                        ;tell DOS to ignore the error
  594.     Pop    DS                          ;restore DS
  595.     Pop    DX                          ;restore DX
  596.     Pop    DI                          ;restore DI
  597.     Iret                               ;get back to dos
  598. Int24ErrHandler EndP 
  599. ;---------------------------------------------------------------------------- 
  600. ;OpenFile - opens a file pointed at by FileName with attribute specified
  601.  
  602. OpenFile   Proc Near, FileName:Word, Attr:Word
  603.                                        ;put a zero on the strings
  604.     Mov    SI,FileName                 ;get address of file
  605.     Mov    DX,SI                       ;save it for use later
  606.     Mov    CX,66                       ;up to 66 characters
  607.                                        ;Just in case file is not an ASCIIz
  608. MakeZStr:                              ;optional, can be commented out
  609.     Lodsb
  610.     Cmp    AL,32
  611.     Jz     @F
  612.     Or     AL,AL
  613.     Jz     @F                          ;already a zero
  614.     Loop   MakeZStr
  615. @@:
  616.     Mov    [SI-1],CH                   ;put a zero in
  617.     Mov    AX,Attr                     ;get attribute (Read/Write)
  618.     Cmp    AH,3Ch                      ;are we forcing a create?
  619.     Jz     @F                          ;yes
  620.     Mov    AH,3Dh                      ;open existing file
  621. @@:
  622.     Xor    CX,CX                       ;clear CX for attributes
  623.     Mov    DX,FileName                 ;get address of filename
  624.     Int    21h                         ;
  625.     Ret
  626. OpenFile   EndP
  627.  
  628. ;--- Seek - positions a file pointer
  629. Seek       Proc Near,  Handle1:Word, Pointer:Dword
  630.     Push   BX
  631.     Mov    ErrorNum,0                  ;reset error number
  632.     Mov    AX,4200h                    ;service 42h, offset from start of file
  633.     Mov    DX,Word Ptr Pointer         ;low value
  634.     Mov    CX,Word Ptr Pointer[2]      ;high value
  635.     Mov    BX,Handle1                  ;file handle to use
  636.     Int    21h
  637.     Jnc    @F
  638.     Mov    ErrorNum,AX                 ;save error number
  639. @@:
  640.     Pop    BX
  641.     Ret                 ;return with new file pointer position in DX:AX
  642. Seek       EndP
  643.  
  644. ;---------------------------------------------------------------------------
  645. ; Read - Reads BufSize number of characters of file data into buffer
  646. ;        pointed at by Buffer parameter.
  647. Read       Proc Near, Handle2:Word, Buffer:Word, BufSize:Word
  648. Reread2:
  649.     Mov    ErrorNum,0                  ;reset error number
  650.     Mov    AH,3Fh                      ;service 3Fh - read file
  651.     Mov    BX,Handle2                  ;file handle
  652.     Mov    CX,BufSize                  ;get number of bytes to read
  653.     Mov    DX,Buffer                   ;get address of buffer
  654.     Int    21h                         ;do it
  655.     Jnc    ReadOk                      ;no errors
  656.     Mov    ErrorNum,AX
  657.     Jmp    ReadExit                    ;we got an error, no need to check anymore
  658.  
  659. ReadOk:
  660.     Clc
  661. ReadExit:
  662.     Ret
  663. Read       EndP
  664.  
  665. ; Write - Writes BufSize number of characters stored in Buffer to file handle
  666. ;          supplied
  667.  
  668. Write      Proc Near, Handle3:Word, Buffer:Word, BufSize:Word
  669. ReWrite:
  670.     Mov    DOSErrCode,0                ;clear the DOS error variable
  671.     Mov    CritErrFlag,0               ;clear the critical error flag
  672.     Mov    ErrorNum,0                  ;reset error number
  673.     Mov    AH,40h                      ;service 40h, write to a file
  674.     Mov    BX,Handle3                  ;file handle
  675.     Mov    CX,BufSize                  ;number of bytes to write
  676.     Mov    DX,Buffer                   ;address of buffer
  677.     Int    21h                         ;write the buffer
  678.     Jnc    NoWriteError                ;no errors, skip ahead
  679.     Jmp    WriteExit
  680.  
  681. NoWriteError:
  682.     Cmp    AX,BufSize                  ;disk full?
  683.     Jz     WriteOk                     ;nope, exit ok
  684.     Stc
  685.     Jmp    WriteExit
  686.  
  687. WriteOk:
  688.     Clc
  689.  
  690. WriteExit:
  691.     Ret 
  692. Write      EndP
  693.  
  694. ;---  Close - Closes file specified by Handle4
  695. Close      Proc Near, Handle4:Word
  696.     Mov    ErrorNum,0                  ;reset error number
  697.     Mov    AH,3Eh                      ;service 3Eh, close file
  698.     Mov    BX,Handle4                  ;file handle
  699.     Int    21h                         ;close the file
  700.     Ret
  701. Close      EndP
  702.  
  703. StrCmp     Proc Near, SrcString:Ptr, CmpString:Ptr, StrLength:Word
  704.     Push   SI                           ;save Regs
  705.     Push   DI
  706.     Push   CX
  707.     Mov    SI,SrcString                 ;get address of source
  708.     Mov    DI,CmpString                 ;and string to compare
  709.     Mov    CX,StrLength                 ;do length
  710.     RepE   CmpSb                        ;compare them
  711.     Mov    AX,CX                        ;result into AX
  712.     Pop    CX                           ;restore regs
  713.     Pop    DI
  714.     Pop    SI
  715.     Ret
  716. StrCmp     EndP
  717.  
  718. CheckDestFile  Proc Near
  719.     Cmp    DestFileThere,-1
  720.     Jz     CheckDestOk
  721.     Cmp    SourceFileThere,-1
  722.     Jnz    CheckDestOk
  723.     Mov    SI,Offset SourceFile         ;get address of source file
  724.     Mov    DI,Offset DestFile           ;get address of dest file
  725.     Push   DS
  726.     Pop    ES                           ;point ES -> DS
  727.     Mov    CX,67                        ;length of file buffer
  728.     Cld                                 ;forward moves
  729.  
  730. FileMoveLoop:
  731.     LodSb                               ;get a character
  732.     Or     AL,AL                        ;is it a zero?
  733.     Jz     PutTXT                       ;yes, put the .TXT in
  734.     Cmp    AL,'.'                       ;ok, how about a period
  735.     Jz     PutTxt2                      ;fine
  736.  
  737. FMIn:
  738.     StoSb
  739.     Loop   FileMoveLoop
  740.     Stc                                 ;error, set carry
  741.     Jmp    CheckDestOk 
  742.  
  743. PutTxt2:
  744.     Cmp    Byte Ptr [SI],'\'            ;is it a slash?
  745.     Jz     FMIn                         ;yes,
  746.     Cmp    Byte Ptr [SI],'.'            ;ok, than is it two dots?
  747.     Jz     FMIn
  748.  
  749. PutTxt:
  750.     Mov    SI,Offset DefaultExtension   ;get address of txt extension
  751.     Mov    CX,4
  752.     Rep    MovSb                        ;stuff it in there
  753.  
  754. FMLOut:
  755.     Xor    AL,AL                        ;store an asciiZ
  756.     StoSb
  757.     Clc                                 ;ok, clear carry
  758.  
  759.  
  760. CheckDestOk:
  761.     Ret
  762. CheckDestFile EndP
  763.  
  764. ;Error message text
  765.    Err02 DB 'File Not Found$'
  766.    Err03 DB 'Path Not Found$'
  767.    Err05 DB 'Access Denied, may be write protected$'
  768.    Err13 DB 'Write Protected$'
  769.    Err15 DB 'Drive Not Ready$'
  770.    Err00 DB 'Unknown Error$'
  771.    PCrLf DB  10,13,'$'
  772.    Beep  DB  07,'$'
  773.    
  774. PrintError  Proc Near           ;incoming AX = error 
  775.     Cmp   CritErrFlag, 0        ;is it a critical error?
  776.     Jz    @F                    ;no, use extended error conversion
  777.     Mov   AX, CS:DOSErrCode     ;get real error saved during int 24h
  778.     Jmp   ErrorDecoder
  779. @@:
  780.     Mov   AH,59h                ;extended error
  781.     Int   21h                   ;decode error
  782.  
  783. ErrorDecoder:
  784.     Cmp   AX, 02h               ;file not found
  785.     Jnz   @F 
  786.     Mov   DX,Offset Err02
  787.     Mov   AX,1
  788.     Jmp   PError
  789. @@:
  790.     Cmp   AX, 03h               ;path not found
  791.     Jnz   @F
  792.     Mov   DX,Offset Err03
  793.     Mov   AX,1
  794.     Jmp   PError
  795. @@:
  796.     Cmp   AX, 05h               ;Access denied
  797.     Jnz   @F
  798.     Mov   DX,Offset Err05
  799.     Mov   AX,1
  800.     Jmp   PError
  801. @@:
  802.     Cmp   AX, 13h               ;write protected
  803.     Jnz   @F
  804.     Mov   DX,Offset Err13
  805.     Mov   AX,3
  806.     Jmp   PError
  807. @@:
  808.     Cmp   AX, 15h               ;drive not ready
  809.     Jnz   @F
  810.     Mov   DX,Offset Err15
  811.     Mov   AX,3
  812.     Jmp   PError
  813. @@:
  814.     Mov   DX,Offset Err00
  815.     
  816. PError:
  817.     Push  AX
  818.     Invoke PrintLine, DX
  819.     Invoke PrintLine, Addr PCRLF
  820.     Invoke PrintLine, Addr Beep
  821.     Pop   AX
  822.     Ret
  823.     
  824. PrintError EndP
  825.  
  826. IsChar Proc Near                ;check AL to see if it's alphanumeric
  827.    Cmp  AL,'0'                  ;is it a number?
  828.    Jl   NoChar
  829.    Cmp  AL,'9'
  830.    Jle  YesChar
  831.    Cmp  AL,'A'                  ;is it in the alpha range?
  832.    Jl   NoChar
  833.    Cmp  AL,'X'
  834.    Jle  YesChar
  835.    Cmp  AL,'a'
  836.    Jl   NoChar
  837.    Cmp  AL,'z'
  838.    Jg   NoChar
  839.  
  840. YesChar:                        ;yes, clear carry flag
  841.    Clc
  842.    RetN
  843. NoChar:                         ;no, set carry (S.O.P. for errors)
  844.    Stc
  845.    RetN
  846. IsChar EndP
  847.  
  848.  
  849. FileExists  DB 'Destination file Exists, Overwrite? Y/N $'
  850.    
  851. ExistYes  Proc Near             ;asks the user if they want to overwrite?
  852.    Invoke PrintLine, Addr FileExists 
  853.    Xor    AX,AX
  854.    Int    16h                   ;wait for a keystroke
  855.    Xor    AH,AH
  856.    Mov    CX,AX
  857.    Mov    AH,02
  858.    Mov    DL,CL
  859.    Int    21h
  860.    Invoke PrintLine, Addr PCRLF
  861.  
  862.    Cmp    CL,'Y'                ;if they said yes, then clear carry
  863.    Jz     YesNukeIt
  864.    Cmp    CL,'y'
  865.    Jz     YesNukeIt
  866.    Stc                          ;if no, then set carry flag
  867.    Jmp    @F    
  868. YesNukeIt:
  869.    Clc
  870. @@:
  871.    Ret
  872. ExistYes  EndP
  873.  
  874. End        Begin                ;tell Masm where execution starts
  875.